/*
 * Copyright (c) 2011 Imre Fazekas.
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the name of the Brillien nor the names of its
 * terms and concepts may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

package com.vii.streamline.services;

import java.io.File;
import java.util.HashMap;
import java.util.List;

/**
 * Service class to handle string-based operations
 */
public class StringServices {

    public static final char[] EMGLISH_ABC;
    public static final char[] EMGLISH_ALNUM_ABC;
    public static final char[] EMGLISH_GRAPH_ABC;


    /**
     * Default delimeter value to separate keys-value pairs in the string reprezentation of a Map instance 
     */
    public static String DEFAULT_DELIMETER = ";";

    /**
     * Default connector value to connect keys with values in the string reprezentation of a Map instance
     */
    public static String DEFAULT_CONNECTOR = "=";


    static{
        EMGLISH_ABC = new char[]{
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
        };
        EMGLISH_ALNUM_ABC = new char[]{
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
        };
        EMGLISH_GRAPH_ABC = new char[]{
                'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
                'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                '!', '#', '$', '%', '&', '*', '+', ',', '-', '.', ':', ';', '?', '@', '_'
                //,'!', '\"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~'
        };
    }

    /**
     * This method capitalizes the given string and replaces all ' ' character occurences with '_'.
     * It converts the string to a Java identifier 
     */
    public static String identifiering( String s ){
        return capitalize( s.trim() ).replace(' ', '_');
    }

    /**
     * Tells whether the s string is a qualified name or not
     */
    public static boolean isQualifiedName( String s ){
        return s != null && s.contains(".");
    }

    /**
     * Gets the package name of the full qualified class name
     * @param s full qualified class name
     */
    public static String getPackageName( String s ){
        return s == null || !s.contains(".") ? null : s.substring(0, s.lastIndexOf(".") );
    }

    /**
     * Gets the class name of the full qualified class name
     * @param s full qualified class name
     */
    public static String getClassName( String s ){
        return s == null || !s.contains(".") ? s : s.substring( s.lastIndexOf(".") + 1 );
    }

    /**
     * Normalizer method to handle null cases
     */
    public static String normalize( String s ){
        return s == null ? "" : s;
    }

    /**
     * Capitalizer method
     */
    public static String capitalize( String s ){
        return Character.toUpperCase( s.charAt(0) ) + s.substring(1);
    }

    /**
     * Deapitalizer method
     */
    public static String decapitalize( String s ){
        return Character.toLowerCase( s.charAt(0) ) + s.substring(1);
    }

    /**
     * Creates a string representation from a HashMap instance. All key will be connected with it's value by using the connector and separated from each other be the delimeter
     * DEFAULT_DELIMETER and DEFAULT_CONNECTOR fields are used
     * @param map map instance to be stringified
     * @param <V> Generic type of the map's key
     * @param <W> Generic type of the map's value
     * @return string reprezentation
     */
    public static <V,W> String getAttributesAsString( HashMap<V,W> map ){
        return getAttributesAsString( map, DEFAULT_DELIMETER );
    }

    /**
     * Creates a string representation from a HashMap instance. All key will be connected with it's value by using the connector and separated from each other be the delimeter
     * DEFAULT_CONNECTOR field is used
     * @param map map instance to be stringified
     * @param delimer delimeter string to separate the key-value pairs
     * @param <V> Generic type of the map's key
     * @param <W> Generic type of the map's value
     * @return string reprezentation
     */
    public static <V,W> String getAttributesAsString( HashMap<V,W> map, String delimer ){
        return getAttributesAsString( map, DEFAULT_CONNECTOR, delimer );
    }

    /**
     * Creates a string representation from a HashMap instance. All key will be connected with it's value by using the connector and separated from each other be the delimeter
     * @param map map instance to be stringified
     * @param connector string to connect the key and it's value
     * @param delimer delimeter string to separate the key-value pairs
     * @param <V> Generic type of the map's key
     * @param <W> Generic type of the map's value
     * @return string reprezentation
     */
    public static <V,W> String getAttributesAsString( HashMap<V,W> map, String connector, String delimer ){
        StringBuilder sb = new StringBuilder();
        for( V v : map.keySet() )
            sb.append( v + connector + map.get(v) + delimer );
        sb.deleteCharAt( sb.length()-1 );
        return sb.toString();
    }

    /**
     * Converts a bunch of object to an array of corresponding String representations
     */
    public static String[] toString( Object... os ){
        String[] res = new String[ os.length ];
        for (int i=0; i<os.length; ++i)
            res[i] = os[i].toString();
        return res;
    }

    /**
     * Converts a bunch of object to an array of corresponding String representations
     */
    public static String stringify( Object... os ){
        StringBuilder res = new StringBuilder();
        for (int i=0; i<os.length; ++i)
            res.append(
                (os[i].getClass().isArray()
                ? stringify( (Object[])os[i] )
                :  os[i].toString()
                ) + " "
            );
        return res.toString();
    }

    /**
     * Converts a bunch of object to an array of corresponding String representations
     */
    public static String stringify( List<Object> os ){
        StringBuilder res = new StringBuilder();
        for (int i=0; i<os.size(); ++i)
            res.append(
                (os.get(i).getClass().isArray()
                ? stringify( (Object[])os.get(i) )                    
                :  os.get(i).toString()
                ) + " "
            );
        return res.toString();
    }

    public static String getClassNameByFileReference( File containerDir, File classReference ){
        String s = classReference.getAbsolutePath();
        String c = containerDir.getAbsolutePath();

        String separatorRegex = File.separator.equals( "\\" ) ? "\\\\" : File.separator;

        String name = s.substring( c.length() + 1 ).replaceAll( separatorRegex, ".");
        return name.substring(0, name.length()-6);
    }

    public static int indexOf( String s, String pattern ){
        int index = s.indexOf( pattern );
        return index >= 0 ? index : s.length();
    }

    public static String removeHTMLTags( String s ){
        return s.replaceAll("\\<.*?\\>", "");
    }

    public static boolean startsWith( String text, String... starts ){
        for( String s : starts )
            if( text.startsWith( s ) )
                return true;
        return false;
    }

}
